困惑的开发人员
ID 令牌和访问令牌:有什么区别?
了解什么是 ID 令牌和访问令牌,以及如何在 OpenID Connect 和 OAuth 上下文中正确使用它
最后更新日期:2021年10月28日
https://auth0.com/blog/id-token-access-token-what-is-the-difference/
“让我们使用令牌来保护此 API 调用。我应该使用 ID 令牌还是访问令牌?🤔 ID 令牌对我来说看起来更好。毕竟,如果我知道用户是谁,我可以做出更好的授权决策,对吧?”
你有没有发现自己提出了类似的论点?基于直觉的选择可能听起来不错,但看起来直观的东西并不总是正确的。对于 ID 和访问令牌,它们具有明确且定义明确的用途,因此应基于此使用它们。使用错误的令牌可能会导致解决方案不安全。
“到底发生了什么变化?它们只是令牌。我可以根据需要使用它们。可能发生的最坏情况是什么?
让我们仔细看看这两种类型的令牌,以更好地了解它们在身份验证和授权过程中的作用。
如果您愿意,还可以观看有关同一主题的此视频:
什么是 ID 令牌?
ID 令牌是证明用户已通过身份验证的项目。它是由OpenID Connect(OIDC)引入的,OpenID Connect是许多身份提供商(如Google,Facebook,当然还有Auth0)使用的身份验证开放标准。查看本文档,了解有关 OpenID Connect 的更多详细信息。让我们快速看一下 OIDC 想要解决的问题。
请考虑下图:
在这里,用户使用其浏览器对OpenID提供程序进行身份验证,并访问Web应用程序。基于 OpenID Connect 的身份验证过程的结果是 ID 令牌,该令牌作为用户已通过身份验证的证明传递给应用程序。
这提供了 ID 令牌是什么的一个非常基本的概念:用户身份验证的证明。让我们看看其他一些细节。
ID 令牌被编码为 JSON Web 令牌 (JWT),这是一种标准格式,允许应用程序轻松检查其内容,并确保它来自预期的颁发者,并且没有其他人对其进行更改。如果您想了解有关 JWT 的更多信息,请查看 JWT 手册。
简单地说,ID令牌的示例如下所示:
1 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwOi8vbXktZG9tYWluLmF1dGgwLmNvbSIsInN1YiI6ImF1dGgwfDEyMzQ1NiIsImF1ZCI6IjEyMzRhYmNkZWYiLCJleHAiOjEzMTEyODE5NzAsImlhdCI6MTMxMTI4MDk3MCwibmFtZSI6IkphbmUgRG9lIiwiZ2l2ZW5fbmFtZSI6IkphbmUiLCJmYW1pbHlfbmFtZSI6IkRvZSJ9.bql-jxlG9B_bielkqOnjTY9Di9FillFb6IMQINXoYsw |
当然,这对人类来说是不可读的,所以你必须解码它才能看到JWT包含的内容。顺便说一句,ID令牌没有加密,而只是Base 64编码。可以使用许多可用库之一对其进行解码,也可以使用 jwt.io 调试器自行检查它。
在不深入细节的情况下,上述 ID 令牌携带的相关信息如下所示:
1 | { |
这些 JSON 属性称为声明,它们是关于用户和令牌本身的声明。有关用户的声明定义了用户的标识。
实际上,OpenID Connect 规范不需要 ID 令牌来声明用户。在其最小的结构中,它没有关于用户的数据;只是有关身份验证操作的信息。
一个重要的主张是索赔。此声明定义令牌的受众,即作为令牌最终接收者的 Web 应用程序。对于 ID 令牌,其值是应使用该令牌的应用程序的客户端 ID。aud
请记住有关受众声明的这个小细节,因为它将帮助您更好地了解其正确的用法。
ID 令牌可能包含有关用户的其他信息,例如其电子邮件地址、图片、生日等。
最后,也许是最重要的事情:ID令牌由颁发者使用其私钥签名。这可以保证令牌的来源,并确保它未被篡改。您可以使用颁发者的公钥来验证这些内容。
现在您知道了什么是 ID 令牌。但是,您可以使用ID令牌做什么?
首先,它证明用户已由您信任的实体(OpenID 提供程序)进行身份验证,因此您可以信任有关其身份的声明。
此外,应用程序还可以通过使用 ID 令牌中包含的有关用户的声明来个性化用户体验。例如,你可以在 UI 上显示他们的姓名,或在其生日当天显示“最良好祝愿”消息。有趣的部分是,您不需要提出其他请求,因此您的应用程序的性能可能会略有提高。
什么是访问令牌?
现在,你已了解 ID 令牌是什么,让我们尝试了解什么是访问令牌。
让我们首先描述访问令牌适合的方案:
在上图中,客户端应用程序希望访问资源,例如,API或其他任何可以防止未经授权访问的内容。该图中的其他两个元素是用户(即资源的所有者)和授权服务器。在此方案中,访问令牌是允许客户端应用程序访问用户资源的项目。它由授权服务器在成功对用户进行身份验证并征得其同意后颁发。
在 OAuth 2 上下文中,访问令牌允许客户端应用程序访问特定资源以代表用户执行特定操作。这就是所谓的委派授权方案:用户委派客户端应用程序代表他们访问资源。这意味着,例如,你可以授权你的LinkedIn应用代表你访问 Twitter 的 API,以便在两个社交平台上交叉发布。请记住,你仅授权LinkedIn在 Twitter 上发布你的帖子。您不会授权它删除它们或更改个人资料的数据或执行其他操作。此限制在委派授权方案中非常重要,可通过作用域实现。作用域是一种允许用户授权第三方应用程序仅执行特定操作的机制。
当然,接收访问令牌的 API 必须确保它实际上是由它信任的授权服务器颁发的有效令牌,并根据与其关联的信息做出授权决策。换句话说,API 需要以某种方式使用该令牌,以便授权客户端应用程序对资源执行所需的操作。
应如何使用访问令牌来做出授权决策取决于许多因素:整体系统体系结构、令牌格式等。例如,访问令牌可以是允许 API 从与授权服务器共享的数据库中检索所需信息的密钥,也可以直接包含编码格式的所需信息。这意味着了解如何检索做出授权决策所需的信息是授权服务器和资源服务器(即API)之间的协议。
OAuth 2 核心规范对访问令牌格式只字未提。它可以是任何格式的字符串。用于访问令牌的常见格式是 JWT,并且可以使用标准结构。但是,这并不意味着访问令牌应采用该格式。
好!现在,你已知道什么是 ID 令牌和访问令牌。🎉 因此,您已经准备好使用它们,而不必担心犯错误。但是,等等。我没有看到你被说服。🤔 也许你需要一些其他信息。还行。因此,让我们看看这些令牌不适合什么。
什么是ID令牌不适合?
开发人员使用 ID 令牌时最常犯的错误之一是使用它来调用 API。
如上所述,ID 令牌证明用户已通过身份验证。在第一方场景中,即在客户端和 API 都由您控制的场景中,您可能会认为您的 ID 令牌适合做出授权决策:也许您需要知道的只是用户身份。
但是,即使在这种情况下,由客户端和 API 组成的应用程序的安全性也可能面临风险。实际上,没有将 ID 令牌绑定到客户端 API 通道的机制。如果攻击者设法窃取了您的ID令牌,他们可以使用它来调用您的API,就像合法客户端一样。
另一方面,对于访问令牌,有一组技术(统称为发送方约束)允许您将访问令牌绑定到特定发送方。这可以保证,即使攻击者窃取了访问令牌,他们也无法使用它来访问 API,因为令牌绑定到最初请求它的客户端。
在第三方客户端想要调用您的 API 的委托授权场景中,您不得使用 ID 令牌来调用 API。除了缺乏将其绑定到客户端的机制之外,还有其他几个原因不这样做。
如果您的 API 接受 ID 令牌作为授权令牌,那么首先,您将忽略受众声明中声明的预期收件人。该声明表示它适用于客户端应用程序,而不是资源服务器(即 API)。
您可能认为这只是一种形式,但这里有安全隐患。
首先,在其他验证检查中,API 不应接受不适合它的令牌。如果是这样,其安全性将面临风险。事实上,如果你的 API 不关心令牌是否适合它,则可以使用从任何客户端应用程序窃取的 ID 令牌来访问你的 API。当然,检查受众只是您的API为防止未经授权的访问而应该做的检查之一。
此外,您的ID令牌将没有授予范围(我知道,这是另一个痛点)。如前所述,作用域允许用户限制客户端应用程序可以代表他们执行的操作。这些作用域与访问令牌相关联,以便 API 知道客户端应用程序可以执行哪些操作,不能执行哪些操作。如果客户端应用程序使用 ID 令牌来调用 API,则忽略此功能,并可能允许应用程序执行用户未授权的操作。
什么是访问令牌不适合?
在访问令牌方面,它被设想为证明您有权访问资源,例如,调用API。
客户端应用程序应仅出于此原因使用它。换句话说,客户端应用程序不应检查访问令牌。它适用于资源服务器,客户端应用程序应将访问令牌视为不透明字符串,即没有特定含义的字符串。即使知道访问令牌格式,也不应尝试在客户端应用程序中解释其内容。如前所述,访问令牌格式是授权服务器和资源服务器之间的协议,客户端应用程序不应入侵。想想如果有一天访问令牌格式发生更改会发生什么情况。如果客户端代码正在检查该访问令牌,则现在它将意外中断。
快速回顾
对 ID 和访问令牌的使用感到困惑是非常普遍的,并且很难围绕这些差异进行思考。也许它主要源于没有清楚地了解OAuth和OpenID Connect规范定义的每个工件的不同目标。此外,了解这些工件最初用于操作的场景对于防止混淆其使用具有重要作用。尽管如此,我希望这个话题现在更清楚一些。
回顾一下,下面简要总结了你对 ID 和访问令牌可以做什么和不能做什么的了解:
如果要查看 ID 和访问令牌的实际效果,请注册免费的 Auth0 帐户,并开始使用首选编程语言和框架在几分钟内向应用程序添加身份验证和授权。